#include "BreakthroughGameSmaller.h"
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstdlib>

using namespace std;

BreakthroughGameSmaller::BreakthroughGameSmaller()
{
    m_name = "Breakthrough Smaller (6x6)";
}

BreakthroughGameSmaller::~BreakthroughGameSmaller()
{
	//TODO: m_board og m_stateHistory cleanup
    //dtor
}

vector<MOVE> BreakthroughGameSmaller::legal(GameBoard state)
{
	vector<MOVE> moves;

	for(int y = 0; y < static_cast<int>(state.size()); y++)
	{
		for(int x = 0; x < static_cast<int>(state[y].size()); x++)
		{
			if(state[y][x] != NULL && state[y][x]->getPlayer() == m_currentPlayer)
			{
				unsigned int toX = x;
				unsigned int toY = y;
				toY = y + (1 - 2*(m_currentPlayer));
				//First checks if it is going out of boundaries
				if(!(toY < 0 || toY > state.size()-1 || toX < 0 || toX > state[0].size()-1))
				{
					if(state[toY][toX] == NULL)
					{
						moves.push_back(MOVE(x, y, toX, toY));
					}
				}

				toY = y + (1 - 2*(m_currentPlayer));
				toX = x + (1 - 2*(m_currentPlayer));
				if(!(toY < 0 || toY > state.size()-1 || toX < 0 || toX > state[0].size()-1))
				{
					if(state[toY][toX] == NULL || state[toY][toX]->getPlayer() != m_currentPlayer)
					{
						moves.push_back(MOVE(x, y, toX, toY));
					}
				}
				toY = y + (1 - 2*(m_currentPlayer));
				toX = x - (1 - 2*(m_currentPlayer));

				if(!(toY < 0 || toY > state.size()-1 || toX < 0 || toX > state[0].size()-1))
				{
					if(state[toY][toX] == NULL || state[toY][toX]->getPlayer() != m_currentPlayer)
					{
						moves.push_back(MOVE(x, y, toX, toY));
					}
				}
			}
		}
	}
	return moves;
}

int BreakthroughGameSmaller::advancedEvaluate()
{
	if(winningState() != -1)
	{
		if(winningState() == m_currentPlayer)
		{
			int max = 99999;
			return max;
		}
		else
		{
			int min = -99999;
			return min;
		}
	}

	int avgCurrentPlrDist = 0;
	int avgOponentPlrDist = 0;
	for(int y = 0; y < static_cast<int>(m_board.size()); y++)
	{
		for(int x = 0; x < static_cast<int>(m_board[y].size()); x++)
		{
			if(m_board[y][x] != NULL)
			{
				if(m_board[y][x]->getPlayer() == m_currentPlayer)
				{
					int dist;
					if(m_board[y][x]->getPlayer() == 0)
						dist = y;
					else
						dist = 7-y;
					avgCurrentPlrDist += dist;
				}
				else
				{
					int dist;
					if(m_board[y][x]->getPlayer() == 0)
						dist = y;
					else
						dist = 7-y;
					avgOponentPlrDist += dist;
				}
			}
		}
	}

	return avgCurrentPlrDist-avgOponentPlrDist;
}

void BreakthroughGameSmaller::setBoard()
{
    // If the board is not empty - clear it
    if (m_board.size() > 0)
    {
        m_board.clear();
    }
    m_stateHistory.clear();

    // Put pieces on the board
    for(int y = 1; y <= 6; y++)
    {
		PieceVector temp;
        for(int x = 1; x <= 6; x++)
        {
			if(y <= 2)
			{
				Piece *piece = new Piece(0, 'P');
				temp.push_back(piece);
			}
			else if(y > 4)
			{
				Piece *piece = new Piece(1, 'P');
				temp.push_back(piece);
			}
			else
				temp.push_back(NULL);
        }
		m_board.push_back(temp);
    }

}

void BreakthroughGameSmaller::displayBoard()
{
    Game::displayBoard();

    // Debug text
    if (m_debug)
    {
        cout << "Debug info" << endl;
        cout << "Current difficulty level: ";
        if (difficulty == DifficultyLevel::Random)
        {
            cout << "random" << endl;
        }
        if (difficulty == DifficultyLevel::Easy)
        {
            cout << "easy" << endl;
        }
        if (difficulty == DifficultyLevel::Medium)
        {
            cout << "medium" << endl;
        }
        if (difficulty == DifficultyLevel::Hard)
        {
            cout << "hard" << endl;
            cout << "Advanced evaluation value: " << advancedEvaluate() << endl;
        }
        else
        {
            cout << "Evaluation value: " << evaluate() << endl;
        }
        cout << "Total moves: " << m_moveCount << endl;
        cout << "State history size: " << m_stateHistory.size() << endl;
        cout << "Current legal moves: " << legal().size() << endl;
    }
}

void BreakthroughGameSmaller::start()
{
    cout << "Welcome to " << m_name << endl;
    Game::init();
    displayBoard();
}

void BreakthroughGameSmaller::movePiece(int fromX, int fromY, int toX, int toY)
{
    MOVE move(fromX, fromY, toX, toY);
    vector<MOVE> legalMoves = legal();
    // If no legal moves exist
    if (legalMoves.size() == 0)
    {
        cerr << "Error: No legal moves found" << endl;
        return;
    }

    vector<MOVE>::iterator it;
    it = find(legalMoves.begin(), legalMoves.end(), move);

    // If the move is legal
    if (it != legalMoves.end())
    {
        // Move source to destination
        m_board[toY][toX] = m_board[fromY][fromX];
        m_board[fromY][fromX] = NULL;

        m_stateHistory.push_back(m_board);
        setCurrentPlayer(abs(m_currentPlayer - 1));
    }
    else
    {
        cerr << "Illegal move" << endl;
        return;
    }
    m_moveCount = m_stateHistory.size() - 1;
    countPieces();
}

int BreakthroughGameSmaller::winningState()
{
	int winner = -1;

	// Check for tie
	if (Game::winningState() == 2)
	{
	    winner = 2;
	    return winner;
	}

    // Check if Player 0 wins
    for(int x = 0; x < static_cast<int>(m_board[5].size()); x++)
    {
        if ((m_board[5][x] != NULL && m_board[5][x]->getPlayer() == 0)
            || numPiecesP2 == 0)
        {
            winner = 0;
            return winner;
        }
    }

    // Check if Player 1 wins
    for(int x = 0; x < static_cast<int>(m_board[0].size()); x++)
    {
        if((m_board[0][x] != NULL && m_board[0][x]->getPlayer() == 1)
           || numPiecesP1 == 0)
        {
            winner = 1;
			return winner;
        }
    }

    // No win
    return winner;
}
